﻿using SearchAlgorithms.Interfaces;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace SearchAlgorithms.Algorithms.Search
{
    public class Brutesearch : ISearchAlgorithm
    {
        public static Brutesearch Default { get; } = new Brutesearch();

        private Brutesearch()
        {
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public int SingleSearch<T>(Span<T> input, ReadOnlySpan<T> search, int start, int count)
            where T : IEquatable<T>
        {
            int j = 0;
            int inputLength = count > input.Length ? input.Length : count;

            for (int i = start; i < inputLength;)
            {
                if (search[j].Equals(input[i]))
                {
                    j++;
                    i++;
                }

                if (j == search.Length)
                {
                    return i - j;
                }

                if (i < inputLength && !search[j].Equals(input[i]))
                {
                    if (j != 0)
                    {
                        j = 0;
                    }
                    else
                    {
                        i++;
                    }
                }
            }

            return -1;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public int SingleSearch<T>(IReadOnlyList<T> input, IReadOnlyList<T> search, int start, int count)
            where T : IEquatable<T>
        {
            int j = 0;
            int inputLength = count > input.Count ? input.Count : count;

            for (int i = start; i < inputLength;)
            {
                if (search[j].Equals(input[i]))
                {
                    j++;
                    i++;
                }

                if (j == search.Count)
                {
                    return i - j;
                }

                if (i < inputLength && !search[j].Equals(input[i]))
                {
                    if (j != 0)
                    {
                        j = 0;
                    }
                    else
                    {
                        i++;
                    }
                }
            }

            return -1;
        }
    }
}